﻿using UnityEngine;
using System.Collections.Generic;
using ZiZi.Graphics.Sampling.VanDerCorput;

namespace ZiZi.Graphics.Sampling.Hammersley
{
    public class HammersleyPointSet
    {
        public static void Value(int index, int totalCount, ref Vector2 result)
        {
            if (index <= 0)
            {
                result.x = 0;
                result.y = 0;
            }
            else
            {
                result.x = (float)index / (float)(totalCount);  
                result.y = (float)VanDerCorputSequence.Value((uint)index);
            }
        }

        public static Vector2 Value(int index, int totalCount)
        {
            if (index <= 0)
            {
                return Vector2.zero;
            }
            else
            {
                return new Vector2((float)index / (float)totalCount, (float)VanDerCorputSequence.Value((uint)index));
            }
        }

        public static void Generate(int count, ref List<Vector2> result)
        {
            result.Clear();
            result.Capacity = count;

            for (int i = 0; i < count; ++i)
            {
                result.Add(HammersleyPointSet.Value(i, count));
            }
        }

        public static Vector3 GetUnitHemisphereRay(Vector2 hammersleyPoint)
        {
            float theta = Mathf.Acos( 1 - hammersleyPoint.x);
            float phi = Mathf.PI * 2 * hammersleyPoint.y;
            float y = Mathf.Cos(theta);
            float SinR = Mathf.Sin(theta);
            float x = SinR * Mathf.Cos(phi);
            float z = SinR * Mathf.Sin(phi);

            return new Vector3(x, y, z);
        }
			
        public static void GetUnitHemisphereRay(Vector2 hammersleyPoint, ref Vector3 result)
        {
            float theta = Mathf.Acos(1 - hammersleyPoint.x);
            float phi = Mathf.PI * 2 * hammersleyPoint.y;
            float y = Mathf.Cos(theta);
            float SinR = Mathf.Sin(theta);
            float x = SinR * Mathf.Cos(phi);
            float z = SinR * Mathf.Sin(phi);

            result.x = x;
            result.y = y;
            result.z = z;
        }

        public static Vector3 GetHemisphereRay(Vector2 hammersleyPoint, float radius)
        {
            float theta = Mathf.Acos(1 - hammersleyPoint.x);
            float phi = Mathf.PI * 2 * hammersleyPoint.y;
            float y = radius * Mathf.Cos(theta);
            float SinR = radius * Mathf.Sin(theta);
            float x = SinR * Mathf.Cos(phi);
            float z = SinR * Mathf.Sin(phi);

            return new Vector3(x, y, z);
        }

    }
}
